﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace CommonHelper
{
    public class TypeHelper
    {
        /// <summary>
        /// 进行模型变化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <returns></returns>
        public static T Transformation<T>(object model)
        {
            if (model == null)
                return default(T);

            T t = CreateInstance<T>();
            Transformation(model, t);

            return t;
        }

        /// <summary>
        /// 进行模型变换
        /// </summary>
        /// <param name="o1"></param>
        /// <param name="o2"></param>
        public static void Transformation(object o1, object o2)
        {
            if (o1 == null || o2 == null)
                return;

            var o1_property = o1.GetType().GetProperties();
            var o2_property = o2.GetType().GetProperties();

            foreach (var o2_item in o2_property)
            {
                var o1_item = o1_property.FirstOrDefault(n => n.Name == o2_item.Name);

                if (o1_item == null)
                    continue;

                if (o1_item.PropertyType == o2_item.PropertyType)
                    o2_item.SetValue(o2, o1_item.GetValue(o1));
            }
        }

        /// <summary>
        /// 转换数据模型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <returns></returns>
        public static T TryChangeType<T>(object model)
        {
            return (T)Convert.ChangeType(model, typeof(T));
        }

        /// <summary>
        /// 尝试转换数据类型
        /// </summary>
        /// <param name="j_data"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private static object TryChangeType(object j_data, Type type)
        {
            return Convert.ChangeType(j_data, type);
        }

        /// <summary>
        /// 在某一个程序集中搜索某一种具体的类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <returns></returns>
        public static IEnumerable<Type> SearchType<T>(string name)
        {
            List<Type> item_types = new List<Type>();

            var parent_type = typeof(T);

            foreach (var item in Assembly.Load(name).GetTypes())
            {
                if (parent_type.IsAssignableFrom(item))
                {
                    item_types.Add(item);
                }
            }

            return item_types;
        }

        /// <summary>
        /// 尝试获取参数
        /// </summary>
        /// <param name="net_data"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public static object TryGetParameter(JObject net_data, ParameterInfo item)
        {
            var j_data = net_data[item.Name];

            return TryGetParameterByType(j_data, item.ParameterType);
        }

        public static object TryGetParameterByType(JToken net_data, Type item)
        {
            if (net_data == null)
                return null;

            if (item == typeof(string))
                return (string)net_data;


            if (item.IsEnum)
                return Enum.Parse(item, net_data.ToString());

            if (item.IsValueType)
                return Convert.ChangeType(net_data, item);

            var obj = CreateInstance(item);

            foreach (var pro_item in obj.GetType().GetProperties())
            {
                var pro_obj = TryGetParameterByType(net_data[pro_item.Name], pro_item.PropertyType);

                if (pro_obj != null)
                    pro_item.SetValue(obj, pro_obj);
            }

            return obj;
        }

        /// <summary>
        /// 根据数据类型创建数据实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="controller_type"></param>
        /// <returns></returns>
        public static T CreateInstance<T>(Type controller_type)
        {
            return (T)controller_type.Assembly.CreateInstance(controller_type.FullName);
        }

        /// <summary>
        /// 创建实例对象
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object CreateInstance(Type type)
        {
            return type.Assembly.CreateInstance(type.FullName);
        }

        /// <summary>
        /// 创建实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T CreateInstance<T>()
        {
            return CreateInstance<T>(typeof(T));
        }
    }

}
